package com.ng8866.gateway.listener;

import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.ng8866.gateway.balancer.LeastConnectionLoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Component
@Order(100)
@ConditionalOnProperty(prefix = "loadBalancer", name = "enableBalancer", havingValue = "true")
public class ServerListChangeEventListener extends Subscriber<InstancesChangeEvent> {

    @PostConstruct
    public void init() {
        NotifyCenter.registerSubscriber(this);
    }


    @Override
    public void onEvent(InstancesChangeEvent event) {
        String serviceName = event.getServiceName();
        List<Instance> instances = event.getHosts();
        if (instances != null) {
            ConcurrentHashMap<String, ConcurrentHashMap<String, AtomicInteger>> loadMap = LeastConnectionLoadBalancer.loadMap;
            // 筛选有效的服务实例
            List<Instance> validInstances = instances.stream()
                    .filter(instance -> instance.isEnabled() && instance.isHealthy() && instance.isEphemeral())
                    .collect(Collectors.toList());
            // 根据筛选后的服务实例更新loadMap
            updateLoadMap(serviceName, loadMap, validInstances);
            log.debug("服务列表数据：{}", loadMap);
        }
    }

    /**
     * 更新负载映射表
     *
     * @param serviceName    服务名称
     * @param loadMap        负载映射表
     * @param validInstances 有效的服务实例列表
     */
    private void updateLoadMap(String serviceName, ConcurrentHashMap<String, ConcurrentHashMap<String, AtomicInteger>> loadMap, List<Instance> validInstances) {
        ConcurrentHashMap<String, AtomicInteger> serviceMap = loadMap.getOrDefault(serviceName, new ConcurrentHashMap<>());
        List<String> instanceKeys = new ArrayList<>();
        for (Instance instance : validInstances) {
            String key = LeastConnectionLoadBalancer.getInstanceKey(instance.getIp(), instance.getPort());
            serviceMap.putIfAbsent(key, new AtomicInteger(0));
            instanceKeys.add(key);
        }
        // 如果服务映射为空，从loadMap中删除该服务
        if (serviceMap.isEmpty()) {
            loadMap.remove(serviceName);
        } else {
            // 删除不在服务列表中的服务
            serviceMap.keySet().removeIf(key -> !instanceKeys.contains(key));
        }
        // 记录处理后的服务列表数据
        log.info("处理后的服务{}列表数据：{}", serviceName, serviceMap);
        // 更新loadMap
        loadMap.putIfAbsent(serviceName, serviceMap);
    }


    @Override
    public Class<? extends Event> subscribeType() {
        return InstancesChangeEvent.class;
    }
}
